
use base64::{Engine as _, engine::general_purpose};

use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, BlockEncryptMut, generic_array::GenericArray, KeyInit,};
use aes::{Aes128Dec, Aes128Enc, Aes256Dec, Aes256Enc};
// const KEY: &[u8; 16] = b"1234567890123456"; // 密钥---16位
/// 加密 AES CBC 256 plain: String key:&[u8; 32]
pub fn encrypt(plain: String,key: &[u8; 32]) -> String {
    
    let plain_bytes = plain.as_bytes();
 
    let size = if plain.len() % 32 == 0 {
        plain.len() + 32
    } else {
        ((plain.len() / 32) + 1) * 32
    };
    let mut buf = vec![0u8; size];
 
    let pt_len = plain.len();
    buf[..pt_len].copy_from_slice(plain_bytes);
    let key = GenericArray::from(key.clone());
    let ct = Aes256Enc::new(&key)
        .encrypt_padded_b2b_mut::<Pkcs7>(plain_bytes, &mut buf)
        .unwrap();
    let crypt_txt = general_purpose::STANDARD.encode(ct);
    crypt_txt
}

use crypto::aes::{cbc_decryptor, cbc_encryptor, KeySize};
use crypto::blockmodes::PkcsPadding;
use crypto::buffer::{BufferResult, ReadBuffer, WriteBuffer};

fn aes_cbc_encrypt(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
    let mut encryptor = cbc_encryptor(
        KeySize::KeySize256,
        key,
        iv,
        PkcsPadding
    );
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = crypto::buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = crypto::buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = encryptor.encrypt(&mut read_buffer, &mut write_buffer, true).unwrap();
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));

        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => {}
        }
    }

    final_result
}

/// 解密 cipher_byte: Vec<u8>: String key:&[u8; 32]
pub fn decrypt(crypt_txt: String,key: &[u8; 32]) -> String {
    let cipher_byte = general_purpose::STANDARD.decode(crypt_txt).unwrap();
    let mut vec_buf = vec![0u8; cipher_byte.len()];
    vec_buf[..cipher_byte.len()].copy_from_slice(&cipher_byte);
 
    let key = GenericArray::from(key.clone());
    let pt = Aes256Dec::new(&key)
        .decrypt_padded_b2b_mut::<Pkcs7>(&cipher_byte, &mut vec_buf)
        .unwrap();
    
    String::from_utf8(pt.to_vec()).unwrap()
}
 
pub fn _encrypt128(plain: String,key: &[u8; 16]) -> Vec<u8> {
    
    let plain_bytes = plain.as_bytes();
 
    let size = if plain.len() % 16 == 0 {
        plain.len() + 16
    } else {
        ((plain.len() / 16) + 1) * 16
    };
    let mut buf = vec![0u8; size];
 
    let pt_len = plain.len();
    buf[..pt_len].copy_from_slice(plain_bytes);
 
    let key = GenericArray::from(key.clone());
    let ct = Aes128Enc::new(&key)
        .encrypt_padded_b2b_mut::<Pkcs7>(plain_bytes, &mut buf)
        .unwrap();
 
    ct.to_vec()
}
 
/// 解密
pub fn _decrypt128(cipher_byte: Vec<u8>,key: &[u8; 16]) -> Vec<u8> {
    
    let mut vec_buf = vec![0u8; cipher_byte.len()];
    vec_buf[..cipher_byte.len()].copy_from_slice(&cipher_byte);
 
    let key = GenericArray::from(key.clone());
    let pt = Aes128Dec::new(&key)
        .decrypt_padded_b2b_mut::<Pkcs7>(&cipher_byte, &mut vec_buf)
        .unwrap();
 
    pt.to_vec()
}


pub fn encrypt_pwd(pwd: &str,uuid:String) -> String{
    let s1 = &uuid[0..21];
    let s2 = &uuid[21..];
    let new_str = s2.to_string()+s1;
    // let b = new_str.as_bytes();
    let key: [u8; 32] = new_str.as_bytes().try_into().unwrap();
    let crypt_text = encrypt(pwd.to_string(), &key);
    let pwd_str =  urlencoding::encode(&crypt_text).to_string();
    pwd_str
}
pub fn decrypt_pwd(pwd: &str,uuid:String) -> String{
    let s1 = &uuid[0..21];
    let s2 = &uuid[21..];
    let new_str = s2.to_string()+s1;
    // let b = new_str.as_bytes();
    let key: [u8; 32] = new_str.as_bytes().try_into().unwrap();
    let pwd_str =  urlencoding::decode(pwd).unwrap().to_string();
    let crypt_text = decrypt(pwd_str, &key);
    crypt_text
}

pub fn get_encode_param(str:&str, random_str:String)-> String {
    // let random_str = uuid();
    let iv = get_login_iv(random_str.as_str());
    if let Ok(iv_t) = iv{
        let key = get_login_key(random_str);
        if let Ok(k) = key{
            let encrypt_text = aes_cbc_encrypt(&k,&iv_t,str.as_bytes());
            let crypt_txt = general_purpose::STANDARD.encode(encrypt_text);
            let pwd_text = urlencoding::encode(crypt_txt.as_str()).to_string();
            return pwd_text
        }
    }
    "".to_string()
}

const LOGIN_KEY_SEED:&[u8] = "This4059is021uleloginShangHaiULE".as_bytes();


/**
 * 计算登录密钥
 *
 * @param randomStr 32位随机字符串
 * @return
 * @throws Exception
 */
pub fn get_login_key(random_str:String) -> Result<Vec<u8>, String> {
    let b1 = random_str.as_bytes();
    let mut b1 = Vec::from(b1);
    swap12(&mut b1);
    let res = byte_xor(&b1, &LOGIN_KEY_SEED);
    res
}

/**
 * 计算登录向量
 *
 * @param randomStr
 * @return
 * @throws Exception
 */
pub fn get_login_iv(random_str:&str) -> Result<Vec<u8>, String> {
    let b1 = random_str.as_bytes();
    let mut b1 = Vec::from(b1);
    swap12(&mut b1);
    let halves_len = random_str.len() / 2;
    let s1 = &b1[0..halves_len]; // 值是token的前一半
    let s2 = &b1[halves_len..random_str.len()]; // 值是token的后一半
    let res = byte_xor(s1, s2);
    match res.clone() {
        Ok(result) => println!("Error: {}", String::from_utf8_lossy(&result)),
        Err(e) => println!("Error: {}", e),
    }
    res
}

/**
 * 两个字符异或操作
 *
 * @param byte1 字节数组1
 * @param byte2 字节数组2
 * @return
 * @throws Exception
 */
fn byte_xor(byte1: &[u8], byte2: &[u8]) -> Result<Vec<u8>, String> {
    if byte1.len() != byte2.len() {
        return Err("两个字节数组长度不一".to_string());
    }

    let mut result = Vec::with_capacity(byte1.len());

    for (b1, b2) in byte1.iter().zip(byte2.iter()) {
        let xor_result = b1 ^ b2;
        result.push(xor_result);
    }
    // 转换非ASCII字符为ASCII范围内的字符
    for i in 0..result.len() {
        let v = result[i] as char;
        if !(v.is_ascii_digit() || v.is_ascii_uppercase() || v.is_ascii_lowercase()) {
            let m = (97 + (result[i] as i32).abs() % 25) as u8; // 模,值在0-25中间
            result[i] = m;
        }
    }

    Ok(result)
}
fn swap12(b1: &mut [u8]) {
    for i in (0..b1.len().saturating_sub(1)).step_by(2) {
        b1.swap(i, i + 1);
    }
}

fn aes_cbc_decrypt(key: &[u8], iv: &[u8], data: &[u8]) -> Vec<u8> {
    let mut decryptor = cbc_decryptor(
        KeySize::KeySize256,
        key,
        iv,
        PkcsPadding
    );
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = crypto::buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = crypto::buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = decryptor.decrypt(&mut read_buffer, &mut write_buffer, true).unwrap();
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));

        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => {}
        }
    }

    final_result
}

#[cfg(test)]
mod tests {
    use crate::apis::local::service::login::uuid;

    use super::*;

    #[test]
    fn it_works() {
        let a1:Vec<i8> = vec![-61, 11, 89, -46, -66, 112, -15, 109, -103, 118, 88, -79, -67, 77, -124, 105];
        let vec_u8: Vec<u8> = a1.into_iter().map(|b| b as u8).collect();
        let crypt_txt = general_purpose::STANDARD.encode(vec_u8);

    // 打印十六进制字符串
    println!("Hexadecimal string: {}", crypt_txt);
        // println!("{}",String::from_utf8(vec_u8).unwrap());
        // println!("{}",Engine::encode(encrypt("123qwe".to_string())));
        // let ming = decrypt(decode("19k9CrYcvnH9rumP48WRBw==").unwrap());
        // println!("{}",String::from_utf8(ming).unwrap());
    }
    #[test]
    fn it_works3() {
        let uuid = "6260468408894459ada48a9a092f06ac".to_string();//uuid();
        let rst = get_encode_param("123qwe",uuid);
        println!("uuid {:?}",rst.as_bytes());
        // let res = get_login_iv(uuid.as_str());
        // println!("res {:?}",res)
    //     let a = "1234".as_bytes();
    //     let mut byte_array = Vec::from(a);
    // swap12(&mut byte_array);
    // println!("{:?}", String::from_utf8_lossy(&byte_array));
    // println!("{:?}", byte_array);

        // const KEY: &[u8; 32] = b"BGYKQ32YOWFQU1BUHCFGSP0QZG4JLLMP"; 
        // let crypt_txt = encrypt("123qwe".to_string(),KEY);
        // println!("{}",crypt_txt);
        // let ming = decrypt(crypt_txt,KEY);
        // println!("{}",ming);

        // let b =byte_xor("1234".as_bytes(),"5678".as_bytes());
        // let s = String::from_utf8_lossy(&b).into_owned();
        // println!(">>>>>>>>>>>>>>>>>>.{}",s);

    //     let byte1 = vec![72, 101, 108, 108, 111]; // "Hello" in ASCII
    // let byte2 = vec![72, 101, 108, 108, 111]; // "Hello" in ASCII
    
    // match byte_xor2("1234".as_bytes(),"5678".as_bytes()) {
    //     Ok(result) => println!("{:?}", String::from_utf8_lossy(&result)),
    //     Err(e) => println!("Error: {}", e),
    // }
    }
}
 
